package com.bungarus.model;

import com.bungarus.busi.InnerClient;
import com.bungarus.cluster.Node;
import com.bungarus.cluster.NodeInfo;
import org.apache.log4j.Logger;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Created by tang on 2018/12/20.
 */
abstract public class AbstractBungarusServerWithMultipleClients extends AbstractBungarusServer{
    final Logger logger = Logger.getLogger(AbstractBungarusServerWithMultipleClients.class);

    private Map<String, List<InnerClient>> mclients = new HashMap<>(0);

    @Override
    public void initClusterAndConnectRemoteNode() throws BungarusServerException{
        try {
            //register myself into a cluster
            register2Cluster();
            //connect to remotes servers (xx layer, yy layer) as client
            boolean again;
            do {
                getNodesInCluster();
                again = remoteServerNodes.size() != getRemoteNodeTags().length;
                if(again) {
                    logger.info("FAILED TO GET CLUSTER NODES!!! Try again...");
                }
                else {
                    for(String CLUSTER_TAG : getRemoteNodeTags()) {
                        if(remoteServerNodes.get(CLUSTER_TAG).size() == 0){
                            logger.info("NO NODES FOUND IN CLUSTER " + CLUSTER_TAG + ", Try again...");
                            again = true;
                            break;
                        }
                    }
                }
                if(again) {
                    Thread.sleep(2000);
                }
            } while (again);

            for (String CLUSTER_TAG : getRemoteNodeTags()) {
                CopyOnWriteArrayList<NodeInfo> queue = remoteServerNodes.get(CLUSTER_TAG);
                List<InnerClient> innerClients = new ArrayList<>();
                for(int i=queue.size()-1;i>=0;i--){
                    try {
                        InnerClient innerClient = this.connect(i, queue);
                        innerClients.add(innerClient);
                    }
                    catch (Exception e){
                        e.printStackTrace();
                    }
                }
                mclients.put(CLUSTER_TAG, innerClients);
            }
            this.setStatus(Node.STATUS_RUNNING);
        }
        catch (Exception e) {
            throw new BungarusServerException(e);
        }
    }

    @Override
    public Map<String, InnerClient> getInnerClients() {
        Map<String, List<InnerClient>> clientsMap = getInnerClientList();
        if(!clientsMap.isEmpty()) {
            Map<String, InnerClient> results = new HashMap<>(0);
            Set<String> keys = clientsMap.keySet();
            keys.forEach(key -> {
                long index = Math.round(Math.random() * clientsMap.size()) % clientsMap.size();
                results.put(key, clientsMap.get(key).get((int)index));
            });
            return results;
        }
        return null;
    }

    public Map<String, List<InnerClient>> getInnerClientList() {
        return mclients;
    }
}
